package com.generator.util;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.generator.entity.GenScheme;
import com.generator.entity.TableColumn;
import com.generator.entity.dto.TableColumnDTO;
import com.google.common.collect.Maps;
import freemarker.template.Template;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 代码生成器   工具类
 *
 * @author ljt
 * @since 2019/6/16
 */
@UtilityClass
public class SysGenUtils {

    private final String ENTITY_JAVA_FTL = "Entity.java.ftl";
    private final String CONTROLLER_JAVA_FTL = "SysController.java.ftl";
    private final String SERVICE_JAVA_FTL = "SysService.java.ftl";
    private final String SERVICE_IMPL_JAVA_FTL = "SysServiceImpl.java.ftl";
    private final String MAPPER_JAVA_FTL = "SysMapper.java.ftl";
    private final String MAPPER_XML_FTL = "SysMapper.xml.ftl";
    private final String APPLICATION_JAVA_FTL = "Application.java.ftl";
	private final String API_JS_FTL = "js.ftl";
//	private final String STORE_JS_FTL = "Store.js.ftl";
	private final String LIST_VUE_FTL = "list.vue.ftl";


    private final String BACK_END_PROJECT = "generator";


    private List<String> getTemplates() {
        List<String> templates = new ArrayList<>();
        templates.add(ENTITY_JAVA_FTL);
        templates.add(MAPPER_JAVA_FTL);
        templates.add(SERVICE_JAVA_FTL);
        templates.add(SERVICE_IMPL_JAVA_FTL);
        templates.add(CONTROLLER_JAVA_FTL);
        templates.add(MAPPER_XML_FTL);
        templates.add(APPLICATION_JAVA_FTL);
		templates.add(API_JS_FTL);
//		templates.add(STORE_JS_FTL);
		templates.add(LIST_VUE_FTL);
        return templates;
    }

    /**
     * 生成代码
     */
    @SneakyThrows
    public static void generatorCode(GenScheme genScheme, List<TableColumn> tableColumns, ZipOutputStream zip) {
        // 拷贝 属性
        List<TableColumnDTO> tableDTOs = CollUtils.copyListProperties(tableColumns, TableColumnDTO.class);
        // 读取配置文件
        Configuration config = getConfig();

        tableDTOs.stream().forEach(column -> {
            column.setLowerAttrName(StrUtil.lowerFirst(StrUtil.toCamelCase(column.getColumnName())));
            column.setAttrType(config.getString(column.getDataType()));
        });
        //封装模板数据
        Map<String, Object> map = Maps.newHashMap();
        map.put("author", genScheme.getAuthor());
        map.put("tableName", genScheme.getTableName());
        map.put("comments", genScheme.getRemark());
        map.put("moduleName", genScheme.getModuleName());
        map.put("className", StrUtil.upperFirst(genScheme.getClassName()));
        map.put("classname", StrUtil.lowerFirst(genScheme.getClassName()));
        map.put("pathName", genScheme.getClassName().toLowerCase());
        map.put("package", genScheme.getPackageName());
        map.put("columns", tableDTOs);
        map.put("datetime", DateUtil.now());

        //获取模板列表
        List<String> templates = getTemplates();

        freemarker.template.Configuration configuration = new freemarker.template.Configuration(freemarker.template.Configuration.getVersion());
        ClassPathResource classPathResource = new ClassPathResource("templates");
        configuration.setDirectoryForTemplateLoading(classPathResource.getFile());

        for (String template : templates) {
            //渲染模板
            Template tpl = configuration.getTemplate(template, CharsetUtil.UTF_8);

            String content = FreeMarkerTemplateUtils.processTemplateIntoString(tpl, map);

            //添加到zip
            zip.putNextEntry(new ZipEntry(Objects
                    .requireNonNull(getFileName(template, genScheme.getClassName()
                            , genScheme.getPackageName(), genScheme.getModuleName()))));
            IoUtil.write(zip, CharsetUtil.UTF_8, false, content);
            zip.closeEntry();

        }
    }


    /**
     * 获取文件名
     */
    private String getFileName(String template, String className, String packageName, String moduleName) {
        String packagePath = BACK_END_PROJECT + File.separator + "xx" + File.separator + "src" + File.separator + "main" + File.separator + "java" + File.separator;
        String webPath = BACK_END_PROJECT + File.separator + "web" + File.separator;
        if (StrUtil.isNotBlank(packageName)) {
            packagePath += packageName.replace(".", File.separator) + File.separator + moduleName + File.separator;
        }

        if (template.contains(ENTITY_JAVA_FTL)) {
            return packagePath + "model" + File.separator + "entity" + File.separator + className + ".java";
        }

        if (template.contains(MAPPER_JAVA_FTL)) {
            return packagePath + "mapper" + File.separator + className + "Mapper.java";
        }
        if (template.contains(MAPPER_XML_FTL)) {
            return packagePath + "mapper" + File.separator + "xml" + File.separator + className + "Mapper.xml";
        }
        if (template.contains(SERVICE_JAVA_FTL)) {
            return packagePath + "service" + File.separator + className + "Service.java";
        }

        if (template.contains(SERVICE_IMPL_JAVA_FTL)) {
            return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
        }

        if (template.contains(CONTROLLER_JAVA_FTL)) {
            return packagePath + "controller" + File.separator + className + "SysApi.java";
        }
        if (template.contains(APPLICATION_JAVA_FTL)) {
            return packagePath + File.separator + className + "App.java";
        }
//		if (template.contains(MAPPER_XML_FTL)) {
//			return BACK_END_PROJECT + File.separator + "ljt"+ File.separator + "src" + File.separator + "main" + File.separator + "resources" + File.separator + "mapper" + File.separator + className + "Mapper.xml";
//		}


		if (template.contains(API_JS_FTL)) {
			return webPath + File.separator  + moduleName+ File.separator +  StrUtil.lowerFirst(className) + ".js";
		}
//
//		if (template.contains(STORE_JS_FTL)) {
//			return webPath  +"store"+ File.separator + "modules" + File.separator  +moduleName + File.separator +  StrUtil.lowerFirst(className) + ".js";
//		}
//
		if (template.contains(LIST_VUE_FTL)) {
			return webPath + File.separator  +moduleName+ File.separator  + StrUtil.lowerFirst(className) + "List.vue";
		}

        return null;
    }

    /**
     * 获取配置信息
     */
    private Configuration getConfig() throws ConfigurationException {
        return new PropertiesConfiguration("generator.properties");
    }

}
